import sys
import random
import itertools
import re

from dictionary import SimpleDictionary as Dictionary


class Letter(object):
	
	point_def = {
		'A':1,
		'B':4,
		'C':4,
		'D':2,
		'E':1,
		'F':4,
		'G':3,
		'H':3,
		'I':1,
		'J':10,
		'K':5,
		'L':2,
		'M':4,
		'N':2,
		'O':1,
		'P':4,
		'Q':10,
		'R':1,
		'S':1,
		'T':1,
		'U':2,
		'V':5,
		'W':4,
		'X':8,
		'Y':3,
		'Z':10,
	}
	
	def __init__(self,char):
		self.char = char
		
	@property
	def points(self):
		return Letter.point_def[self.char.upper()]
		

class Board(object):

	square_def = [
		(1,'letter'), #0
		(2,'letter'), #1
		(3,'letter'), #2
		(2,'word'),	#3
		(3,'word')  #4
	]

	board_def = [
		'000400202004000',
		'001003000300100',
		'010010000010010',
		'400200030002004',
		'001000101000100',
		'030002000200030',
		'200010000010002',
		'000300000003000',
		'200010000010002',
		'030002000200030',
		'001000101000100',
		'400200030002004',
		'010010000010010',
		'001003000300100',
		'000400202004000',
	]

	size = 15

	class Square(object):
		def __init__(self,board,multiplier=1,acts_on='letter'):
			self.board = board
			self.multiplier = multiplier
			self.acts_on = acts_on
			self.letter = None
			
		def __str__(self): return self.letter
		
		def up(self): return self.board.up(self)
		def down(self): return self.board.down(self)
		def left(self): return self.board.left(self)
		def right(self): return self.board.right(self)	

	def __init__(self):
		self._board = []
		self._square_locs = {}
		
		for i in xrange(Board.size):
			self._board.append([])
			for j in xrange(Board.size):
				self._board[-1] = Board.Square(self,*Board.square_def[int(Board.board_def[i][j])])
				self._square_locs[self._board[-1]] = (i,j)
		
		self.unique_name = ''.join([random.choice(string.letters) for i in xrange(6)])

	def at(self,x,y):
		if x < 0 or y < 0 or x >= self.size or y >= self.size:
			return None
		return self._board[x][y]
		
	def up(self,square):
		self.at(self._square_locs[square][0],self._square_locs[square][1]-1)
		
	def down(self,square):
		self.at(self._square_locs[square][0],self._square_locs[square][1]+1)
		
	def left(self,square):
		self.at(self._square_locs[square][0]-1,self._square_locs[square][1])
		
	def right(self,square):
		self.at(self._square_locs[square][0]+1,self._square_locs[square][1])
		

	@staticmethod
	def load_from(filename):
		fp = open(filename,'r')
		b = Board()
		for i,line in enumerate(fp.readlines()):
			for j,x in enumerate(line):
				if x == '0': continue
				b.at(i,j).letter = Letter(x)	
		fp.close()
		b.unique_name = filename[:-6]
		return b
		
	def save(self):
		fp = open(self.unique_name+'.words','w')
		fp.write(self)
		fp.close()
	
	def occupied(self):
		return Board.OccupiedIterator(self)
	
	class OccupiedSquareIterator(object):
		def __init__(self,board):
			self.board = board
		
		def __iter__(self):
			return self
			
		def next(self):
			for i in xrange(0,self.board.size):
				for j in xrange(0,self.board.size):
					sq = self.board.at(i,j)
					if sq and sq.letter:
						yield sq
						
	
	
	def __str__(self):
		return '\n'.join([''.join([x for x in line]) for line in self._board])
	
	def find_new_words(self,letters):
		unplaced_letters = [Letter(x) for x in letters]
		
		# Setup dictionary
		dic = Dictionary(pre_index_snippets=True,debug=True)
		
		# Look at every occupied square on the board
		for occupied_square in self.occupied():
			
			print "Checking square (%s): %s" % (occupied_square,)
			
			directions = ['up','down','left','right']
			check_word = occupied_square.letter.char
			check_square = occupied_square
			remaining_letters = unplaced_letters
			for direction in directions:
				
				while check_square: # While the next square is on the board
					if not check_square.letter:
						check_word += remaining_letters.pop()
					else:
						check_word += check_square.letter.char
					
					
					check_square = getattr(self,direction)(check_square)
				
		
		
		# Look at every permutation of the given letters
		# with lengths between 1 and the number of letters
		for check_length in xrange(1,len(letters)+1):
			for check in itertools.permutations(letters,check_length):
				for i in xrange(Board.size):
					for j in xrange(Board.size):
						for num,char in enumerate(check):
							pass


class Helper():
	def __init__(self,min=1,max=float('inf')):
		self.d = Dictionary.load(debug=True)#,pre_index_snippets=True)
		self.min = min
		self.max = max
		
	def help(self,requirements,letters,min=None,max=None):
		
		if not min and min != 0: min=self.min
		if not max: max=self.max
		
		# Do this the 'dumb' way, we find all possible combinations with 
		# letters in 'letters' and the letters in 'requirements'
		# and THEN apply the constraints
		
		found = []
		r = list(requirements)
		l = list(letters)
		
		if '|' in r:
			if not r.startswith('|') and not r.endswith('|'):
				raise ValueError,"Word end marker '|' found in middle of requirements. Must be at either end."
		
		def check(checking,leftovers):
			
			if not self.d.checkPrefix(checking):
				return
			if len(checking) > max:
				return

			for l in remaining_letters:
				leftovers = tuple([j for j in remaining_letters if j != l])
				check(checking + l, leftovers)

			if dictionary.checkWord(checking) \
				and len(checking) >= min \
				and checking not in found_words:
					found.append(checking)
		
		check('',l)
		
		found = [w for w in found if len(w) >= min and len(w) <= max]
		
		r_re_str = '.*' + str(r).replace('-','.') + '.*'
		r_re = re.compile(r_re_str)
		
		for w in found:
			if r_re.match(w): found.append(w)
		
		return found
				
					
	
def cheat():
	current = ''
	while True:
		while not current or len(current) != 7:
			current = raw_input('Letters: ')
		


def main(args):
	pass

if __name__ == '__main__':
	main(sys.argv)